package parser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import compiler.CompilerMain;

import tree.*;
import lexer.*;

/**
 * Class representing the core of SO-Compiler. This is the centre of all parsing
 * processes occurring during compilation process. The Parser is a tool, that
 * transform the given token stream from the lexer ({@link lexer.Lexer}, in a
 * new representation, AST {@link tree.Tree}. The abstract syntax tree allows
 * better and easier analyse of the tree. The tree is built by an abstract
 * factory. {@link tree.TreeFactory}. The parser is also the base for the
 * analyse phases, annotating the tree with important values (
 * {@link parser.Parser#currentInstanceNumber},
 * {@link parser.Parser#currentLocalVar}, {@link parser.Parser#currentMethodVar}
 * , {@link parser.Parser#currentTypeVar}). For further information, please
 * consult the documentation.
 * 
 * @author sebastian
 */
public class Parser {

	/**
	 * A Tree-Factory, provides an unified interface for the creation of trees
	 * and subtrees
	 */
	private TreeFactory factory;

	/**
	 * Number that counts the position of field variables within a class. For
	 * each class, the counter is set to 0.
	 */
	private static int currentInstanceNumber = 0;

	/**
	 * Unique number that helps in analysis phase to identify localVars by this
	 * number
	 */
	private static int currentLocalVar = 0;

	/**
	 * Unique number that helps in analysis phase to identify methods by this
	 * number
	 */
	private static int currentMethodVar = 0;

	/**
	 * Unique number that helps in analysis phase to identify any
	 * type-declaration like classes or interfaces by this number
	 */
	private static int currentTypeVar = 0;

	/**
	 * Lists the whole programme in linear Order
	 */
	private List<Token> TokenList = new ArrayList<Token>();
	/**
	 * Index for the position of the current Token in TokenList
	 */
	private int pointer;

	/**
	 * Constructor for a parser. It takes a Tree-Factory, a lexer that provides
	 * an iterator over all Tokens. If the Source-File is empty , a
	 * ParserException is thrown.
	 * 
	 * @param factory
	 *            the Tree-Factory, provides interface to build up trees (AST)
	 * @param lexer
	 *            the lexer, provides token stream
	 * @throws ParserException
	 */
	public Parser(TreeFactory factory, Lexer lexer) throws ParserException {
		this.factory = factory;
		this.pointer = 0;
		if (lexer.hasNext()) {
			this.TokenList = lexer.getTokenList();
		} else {
			throw new ParserException("Sourcecode-File is empty");
		}
	}

	/**
	 * Transforms a Token to a corresponding type
	 * 
	 * @param t
	 *            the token
	 * @return the corresponding type
	 * @throws ParserException
	 *             if Token doesn't represent a type
	 */
	protected Type toPrimitiveAndReferenceType(Token t) throws ParserException {
		switch (t.getType()) {
		case STRING_TYPE:
			return new Type(DataType.ARR, new Type(DataType.CHAR, ""));
		case CHAR_TYPE:
			return new Type(DataType.CHAR, "");
		case VOID_TYPE:
			return new Type(DataType.VOID, "");
		case INT_TYPE:
			return new Type(DataType.INT, "");
		case DOUBLE_TYPE:
			return new Type(DataType.DOUBLE, "");
		case BOOL_TYPE:
			return new Type(DataType.BOOL, "");
		case IDENT:
			return new Type(DataType.REF, t.getText());
		default:
			throw new ParserException(
					"Error while Parsing: Type expected but was "
							+ t.getType().name());
		}
	}

	/**
	 * Packs a type into an array Type
	 * 
	 * @param ty
	 *            the type
	 * @return the resulting array Type
	 */
	protected Type toArrayType(Type ty) {
		return new Type(DataType.ARR, ty);
	}

	/**
	 * Returns true if the current Token is a modifier
	 * 
	 * @return peek(modifiers)
	 */
	protected boolean isModifier() {
		return peek(TokenType.PUBLIC, TokenType.PRIVATE, TokenType.PROTECTED,
				TokenType.CONST, TokenType.STATIC, TokenType.OVERRIDE);
	}

	/**
	 * Returns true, if the current Token has one of the given TokenType
	 * 
	 * @param tokenTypes
	 *            the expected TokenTypes
	 * @return true, if the current Token has one of the given TokenTypes
	 */
	protected boolean peek(TokenType... tokenTypes) {
		for (TokenType t : tokenTypes) {
			if (this.TokenList.get(this.pointer).getType().equals(t))
				return true;
		}
		return false;
	}

	/**
	 * Returns the current Token, if it has one of the given TokenTypes. The
	 * current Token is updated. Otherwise a ParserException is thrown
	 * 
	 * @param tokenTypes
	 * @return the current token
	 * @throws ParserException
	 */
	protected Token accept(TokenType... tokenTypes) throws ParserException {
		if (peek(tokenTypes)) {
			Token res = this.TokenList.get(this.pointer);
			pointer = pointer + 1;
			if (pointer > this.TokenList.size()) {
				throw new ParserException("Reached end of File with errors.");
			}
			return res;
		}
		throw ParserException.UnexpectedToken(this.TokenList.get(pointer),
				tokenTypes);
	}

	/**
	 * Method decreases pointer. You go one step back in the linear List of
	 * Token
	 */
	protected void returnMethod() {
		pointer = pointer - 1;
	}

	/**
	 * Parse function, calls sub-parse-methods recursively and returns the
	 * resulting tree. It throws a ParserException if the token stream doesn't
	 * match with the SO grammar
	 * 
	 * @param isImport
	 *            , if the file to parse is an import
	 * @return a tree (AST) that represents the sourcecode-file
	 * @throws ParserException
	 */
	public Tree parse(boolean isImport) throws ParserException {
		if (peek(TokenType.EOF))
			return factory.makeProgram(new Token[] { new Token(0, 0,
					TokenType.NONE, "") }, new HashMap<String, Tree>(),
					new Tree[0]);
		return parseProgram(isImport);
	}

	/**
	 * Parses MainClass-declaration, then calls the parse-method for imports and
	 * then the parse methods for classes and merge the resulting trees in a
	 * Program-Tree
	 * 
	 * @param isImport
	 *            , if the file to parse is an imported file
	 * @return a AST representing a program
	 * @throws ParserException
	 */
	protected Tree parseProgram(boolean isImport) throws ParserException {
		List<Tree> classList = new ArrayList<Tree>();
		Map<String, Tree> importFiles = new HashMap<String, Tree>();
		accept(TokenType.MAINCLASS);
		accept(TokenType.COLON);
		Token[] mainClassName;
		if (peek(TokenType.NONE))
			mainClassName = new Token[] { accept(TokenType.NONE) };
		else {
			List<Token> tl = new ArrayList<Token>();
			while (!peek(TokenType.SEMI)) {
				tl.add(accept(TokenType.IDENT));
				if (!peek(TokenType.SEMI))
					accept(TokenType.POINT);
			}
			mainClassName = tl.toArray(new Token[tl.size()]);
		}
		accept(TokenType.SEMI);
		while (peek(TokenType.IMPORT)) {
			addImport(importFiles);
		}
		while (!peek(TokenType.EOF))
			classList.add(parseTypedeclaration());
		if (isImport) {
			return this.factory.makeImport(mainClassName, importFiles,
					classList.toArray(new Tree[0]));
		}
		return this.factory.makeProgram(mainClassName, importFiles, classList
				.toArray(new Tree[0]));
	}

	/**
	 * Parses an import and adds it to the given Map
	 * 
	 * @param stringTreeMap
	 *            , the map where to add the parsed import file
	 * @throws ParserException
	 */
	protected void addImport(Map<String, Tree> stringTreeMap)
			throws ParserException {
		Tree resultProgram = null;
		accept(TokenType.IMPORT);
		String filename = parseFileName();
		String importSourceCode = CompilerMain.readFile(filename,
				"Import Datei" + filename);
		resultProgram = new Parser(factory, new Lexer(importSourceCode))
				.parse(true);
		accept(TokenType.AS);
		Token tok = accept(TokenType.IDENT);
		stringTreeMap.put(tok.getText(), resultProgram);
		accept(TokenType.SEMI);
	}

	/**
	 * Parses a filename and returns it in String representation
	 * 
	 * @return the filename as String
	 * @throws ParserException
	 */
	protected String parseFileName() throws ParserException {
		String result = "";
		while (!peek(TokenType.AS)) {
			if (peek(TokenType.IDENT))
				result += accept(TokenType.IDENT).getText();
			else
				result += accept(TokenType.SEMI, TokenType.IDENT,
						TokenType.DIVORSLASH, TokenType.BACKSLASH,
						TokenType.COLON, TokenType.POINT).getType().getText();
		}
		return result;
	}

	/**
	 * Parses a typeDeclaration, such as classes, interfaces, enumeration types
	 * as well as templates. This method only calls the equivalent parsing
	 * sub-methods
	 * 
	 * @return tree, corresponding to a class, interface, enumeration type,
	 *         template
	 * @throws ParserException
	 *             If an illegal token sequence is found
	 */
	protected Tree parseTypedeclaration() throws ParserException {
		if (peek(TokenType.CLASS)) {
			return parseClass();
		} else if (peek(TokenType.INTERFACE)) {
			return parseInterface();
		} else if (peek(TokenType.ENUM)) {
			return parseEnum();
		} else {
			accept(TokenType.CLASS, TokenType.INTERFACE, TokenType.ENUM);
			return null;
		}
	}

	/**
	 * Parses an interface declaration. Calls sub-routines to parse the body
	 * 
	 * @return tree corresponding to the interface, the SO-source-code
	 *         represents
	 * @throws ParserException
	 *             If the interface-declaration contains an illegal token
	 *             sequence
	 */
	protected Tree parseInterface() throws ParserException {
		currentInstanceNumber = 0;
		accept(TokenType.INTERFACE);
		Token t = accept(TokenType.IDENT);
		Type[] extendsArray = parseExtends();
		Tree body = parseInterfaceBody();
		return factory.makeInterfaceDecl(t, currentTypeVar++, extendsArray,
				body);
	}

	/**
	 * Parses a list of reference-types, a class, an interface or a template
	 * inherits from.
	 * 
	 * @return Type[]-array of the reference-types
	 * @throws ParserException
	 *             If the given extends-list contains illegal tokens
	 */
	protected Type[] parseExtends() throws ParserException {
		List<Type> typl = new ArrayList<Type>();
		if (peek(TokenType.EXTENDS)) {
			accept(TokenType.EXTENDS);
			while (!peek(TokenType.LBRACE, TokenType.IMPLEMENTS)) {
				typl.add(toPrimitiveAndReferenceType(accept(TokenType.IDENT)));
				if (!peek(TokenType.LBRACE, TokenType.IMPLEMENTS)) {
					accept(TokenType.COMMA, TokenType.LBRACE,
							TokenType.IMPLEMENTS);
				}
			}
		}
		return typl.toArray(new Type[0]);
	}

	/**
	 * Parses a list of reference-types (interfaces), a class, an interface or a
	 * template implements.
	 * 
	 * @return Type[]-array of the reference-types
	 * @throws ParserException
	 *             If the given implements-list contains illegal tokens
	 */
	protected Type[] parseImplements() throws ParserException {
		List<Type> typl = new ArrayList<Type>();
		if (peek(TokenType.IMPLEMENTS)) {
			accept(TokenType.IMPLEMENTS);
			while (!peek(TokenType.LBRACE)) {
				typl.add(toPrimitiveAndReferenceType(accept(TokenType.IDENT)));
				if (!peek(TokenType.LBRACE)) {
					accept(TokenType.COMMA, TokenType.LBRACE);
				}
			}
		}
		return typl.toArray(new Type[0]);
	}

	/**
	 * Parses an enumeration type declaration. At the moment it throws an
	 * UnsupportedOperationException.
	 * 
	 * @return a tree, representing the given enumeration type declaration.
	 * @throws ParserException
	 *             If the declaration contains an illegal token sequence.
	 */
	protected Tree parseEnum() throws ParserException {
		throw new UnsupportedOperationException(
				"Enumeration are only supported in the next" + "generation!");
	}

	/**
	 * Parses a class declaration, that is represented by the given
	 * SO-source-code.
	 * 
	 * @return a tree for the corresponding class declaration
	 * @throws ParserException
	 *             If the declaration contains illegal tokens.
	 */
	protected Tree parseClass() throws ParserException {
		currentInstanceNumber = 0;
		accept(TokenType.CLASS);
		Token tok = accept(TokenType.IDENT);
		Type[] extendsArr = parseExtends();
		Type[] implementsArr = parseImplements();
		Tree body = parseClassBody(tok);
		return factory.makeClassDecl(tok, currentTypeVar++, extendsArr,
				implementsArr, body);
	}

	/**
	 * Method to parse a type. e.g.: void, int, long, boolean, float, double,
	 * char, string, reference-type, any array-type
	 * 
	 * @param useVoid
	 *            indicates if this method should ignore void-type or not
	 * @return a type representing the given code sequence
	 * @throws ParserException
	 *             If an illegal token occurs during type-parsing.
	 */
	protected Type parseType(boolean useVoid) throws ParserException {
		if (useVoid) {
			if (peek(TokenType.VOID_TYPE)) {
				return this
						.toPrimitiveAndReferenceType(accept(TokenType.VOID_TYPE));
			}
		}
		Type basicTy = this
				.toPrimitiveAndReferenceType(accept(TokenType.INT_TYPE,
						TokenType.BOOL_TYPE, TokenType.LONG_TYPE,
						TokenType.FLOAT_TYPE, TokenType.DOUBLE_TYPE,
						TokenType.IDENT, TokenType.LONG_TYPE,
						TokenType.CHAR_TYPE, TokenType.STRING_TYPE));
		while (peek(TokenType.LSQBRAC)) {
			accept(TokenType.LSQBRAC);
			accept(TokenType.RSQBRAC);
			basicTy = this.toArrayType(basicTy);
		}
		return basicTy;
	}

	/**
	 * Method to parse the body of an interface, specified by the SO-source
	 * code. The necessary sub-routines are called, e.g.: parseMethodHeader(),
	 * ...
	 * 
	 * @return a tree representing the interface body
	 * @throws ParserException
	 *             If an error occur during parsing the interface body
	 */
	protected Tree parseInterfaceBody() throws ParserException {
		Tree result = null;
		List<Tree> tempTrees = new ArrayList<Tree>();
		accept(TokenType.LBRACE);
		while (isModifier()
				|| peek(TokenType.INT_TYPE, TokenType.BOOL_TYPE,
						TokenType.LONG_TYPE, TokenType.FLOAT_TYPE,
						TokenType.DOUBLE_TYPE, TokenType.IDENT,
						TokenType.LONG_TYPE, TokenType.CHAR_TYPE,
						TokenType.STRING_TYPE, TokenType.VOID_TYPE)) {
			List<Modifiers> ml = new ArrayList<Modifiers>();
			ml = parseModifiers();
			Type t = this.parseType(true);
			Token tok = accept(TokenType.IDENT);
			if (peek(TokenType.SEMI)) {
				tempTrees.add(factory.makeGlobalDecl(ml, tok, t,
						currentInstanceNumber++));
				accept(TokenType.SEMI);
			} else if (peek(TokenType.ASSIGN)) {
				tempTrees.add(parseAssignment(factory.makeGlobalDecl(ml, tok,
						t, currentInstanceNumber++)));
				accept(TokenType.SEMI);
			} else if (peek(TokenType.LPAREN)) {
				tempTrees.add(parseMethodHeader(ml, tok, t));
				accept(TokenType.SEMI);
			} else {
				accept(TokenType.SEMI, TokenType.ASSIGN, TokenType.LPAREN);
			}
		}
		accept(TokenType.RBRACE);
		result = factory.makeBlock(tempTrees
				.toArray(new Tree[tempTrees.size()]));
		return result;
	}

	/**
	 * Method to parse a variable number of modifiers like static, override,
	 * public, etc. pp.
	 * 
	 * @return List<Modifiers> containing all modifiers in a declaration of any
	 *         kind
	 * @throws ParserException
	 *             If an internal error occurs
	 */
	protected List<Modifiers> parseModifiers() throws ParserException {
		List<Modifiers> r = new ArrayList<Modifiers>();
		while (isModifier()) {
			if (peek(TokenType.PUBLIC)) {
				accept(TokenType.PUBLIC);
				r.add(Modifiers.PUBLIC);
			} else if (peek(TokenType.PRIVATE)) {
				accept(TokenType.PRIVATE);
				r.add(Modifiers.PRIVATE);
			} else if (peek(TokenType.PROTECTED)) {
				accept(TokenType.PROTECTED);
				r.add(Modifiers.PROTECTED);
			} else if (peek(TokenType.CONST)) {
				accept(TokenType.CONST);
				r.add(Modifiers.CONST);
			} else if (peek(TokenType.STATIC)) {
				accept(TokenType.STATIC);
				r.add(Modifiers.STATIC);
			} else if (peek(TokenType.OVERRIDE)) {
				accept(TokenType.OVERRIDE);
				r.add(Modifiers.OVERRIDE);
			} else {
				accept(TokenType.PUBLIC, TokenType.PRIVATE,
						TokenType.PROTECTED, TokenType.STATIC, TokenType.CONST,
						TokenType.OVERRIDE);
			}
		}
		return r;
	}

	/**
	 * Method that parses a minimal, standard assignment (only Token ('=','')).
	 * 
	 * @param leftside
	 *            tree representing the left side of the assignment (already
	 *            parsed)
	 * @return tree representing the given assignment
	 * @throws ParserException
	 *             If the assignment contains an illegal token sequence.
	 */
	protected Tree parseAssignment(Tree leftside) throws ParserException {
		Token tok = accept(TokenType.ASSIGN);
		Tree right = parseExpr();
		return factory.makeAssign(tok, leftside, right);
	}

	/**
	 * Method that parses the body of a class. The necessary sub-routines are
	 * called.
	 * 
	 * @param interfacename
	 *            token representing the name of the surrounding class
	 * @return tree representing the body
	 * @throws ParserException
	 *             If token sequence is illegal.
	 */
	protected Tree parseClassBody(Token interfacename) throws ParserException {
		List<Tree> bodyList = new ArrayList<Tree>();
		boolean constructorPossible = true;
		accept(TokenType.LBRACE);
		// Statements starting with static (checking static initialiser)
		if (peek(TokenType.STATIC)) {
			Token t = accept(TokenType.STATIC);
			if (peek(TokenType.LBRACE)) {
				Tree body = parseStmt();
				bodyList.add(factory.makeStaticInitializer(t, body));
			} else {
				List<Modifiers> modL = parseModifiers();
				modL.add(Modifiers.STATIC);
				if (peek(TokenType.CONSTRUCT)) {
					bodyList.add(parseConstructor(this
							.toPrimitiveAndReferenceType(interfacename), modL));
					constructorPossible = true;
				} else {
					Type ty = this.parseType(true);
					Token id = accept(TokenType.IDENT);
					if (peek(TokenType.SEMI)) {
						bodyList.add(factory.makeGlobalDecl(modL, id, ty,
								currentInstanceNumber++));
						accept(TokenType.SEMI);
					} else if (peek(TokenType.ASSIGN)) {
						bodyList.add(this.parseAssignment(factory
								.makeGlobalDecl(modL, id, ty,
										currentInstanceNumber++)));
						accept(TokenType.SEMI);
					} else if (peek(TokenType.LPAREN)) {
						bodyList.add(this.parseMethod(modL, id, ty, this
								.toPrimitiveAndReferenceType(interfacename)));
						accept(TokenType.SEMI);
					} else {
						accept(TokenType.SEMI, TokenType.ASSIGN,
								TokenType.LPAREN);
					}
				}
			}
		}
		// parsing constructors
		while (constructorPossible && peek(TokenType.CONSTRUCT)) {
			bodyList.add(parseConstructor(this
					.toPrimitiveAndReferenceType(interfacename)));
			while (peek(TokenType.CONSTRUCT)) {
				bodyList.add(parseConstructor(this
						.toPrimitiveAndReferenceType(interfacename)));
			}
			if (isModifier()) {
				List<Modifiers> modL = parseModifiers();
				if (peek(TokenType.CONSTRUCT)) {
					bodyList.add(parseConstructor(this
							.toPrimitiveAndReferenceType(interfacename), modL));
				} else {
					constructorPossible = false;
					Type ty = this.parseType(true);
					Token id = accept(TokenType.IDENT);
					if (peek(TokenType.SEMI)) {
						bodyList.add(factory.makeGlobalDecl(modL, id, ty,
								currentInstanceNumber++));
						accept(TokenType.SEMI);
					} else if (peek(TokenType.ASSIGN)) {
						bodyList.add(this.parseAssignment(factory
								.makeGlobalDecl(modL, id, ty,
										currentInstanceNumber++)));
						accept(TokenType.SEMI);
					} else if (peek(TokenType.LPAREN)) {
						bodyList.add(this.parseMethod(modL, id, ty, this
								.toPrimitiveAndReferenceType(interfacename)));
						accept(TokenType.SEMI);
					} else {
						accept(TokenType.SEMI, TokenType.ASSIGN,
								TokenType.LPAREN);
					}
				}
			} else {
				break;
			}
		}
		// parsing other statements, assignment, method-declarations
		while (!peek(TokenType.RBRACE)) {
			List<Modifiers> modL = parseModifiers();
			Type ty = this.parseType(true);
			Token id = accept(TokenType.IDENT);
			if (peek(TokenType.SEMI)) {
				bodyList.add(factory.makeGlobalDecl(modL, id, ty,
						currentInstanceNumber++));
				accept(TokenType.SEMI);
			} else if (peek(TokenType.ASSIGN)) {
				bodyList.add(this.parseAssignment(factory.makeGlobalDecl(modL,
						id, ty, currentInstanceNumber++)));
				accept(TokenType.SEMI);
			} else if (peek(TokenType.LPAREN)) {
				bodyList.add(this.parseMethod(modL, id, ty, this
						.toPrimitiveAndReferenceType(interfacename)));
			} else {
				accept(TokenType.SEMI, TokenType.ASSIGN, TokenType.LPAREN);
			}
		}
		accept(TokenType.RBRACE);
		return factory.makeBlock(bodyList.toArray(new Tree[0]));
	}

	/**
	 * Method, that parses a constructor given by SO-source code sequence. Class
	 * other parseConstructor()-method.
	 * 
	 * @param interfaceTyp
	 *            the name of the surrounding class
	 * @return tree representing the constructor
	 * @throws ParserException
	 *             If an illegal token error occurs.
	 */
	protected Tree parseConstructor(Type interfaceTyp) throws ParserException {
		return parseConstructor(interfaceTyp, parseModifiers());
	}

	/**
	 * Method, that parses a constructor given by SO-source code sequence.
	 * 
	 * @param interfaceTyp
	 *            the name of the surrounding class
	 * @param modl
	 *            list of modifiers, specifying the constructor access
	 * @return tree representing the constructor
	 * @throws ParserException
	 *             If an illegal token error occurs.
	 */
	protected Tree parseConstructor(Type interfaceTyp, List<Modifiers> modl)
			throws ParserException {
		Token tok = accept(TokenType.CONSTRUCT);
		List<Tree> paramList = new ArrayList<Tree>();
		List<Tree> stmtsList = new ArrayList<Tree>();
		List<Type> throwsList = new ArrayList<Type>();
		accept(TokenType.LPAREN);
		paramList = parseParamList();
		paramList.add(0, factory.makeDecl(new Token(-1, -1, TokenType.IDENT,
				"this"), interfaceTyp, currentLocalVar++));
		accept(TokenType.RPAREN);
		throwsList = parseThrows();
		accept(TokenType.LBRACE);
		boolean noConstructorInvokation = false;
		while (peek(TokenType.THIS) && (!noConstructorInvokation)) {
			Token tmp = accept(TokenType.THIS);
			if (peek(TokenType.LPAREN)) {
				accept(TokenType.LPAREN);
				Tree expL = parseExprList();
				accept(TokenType.RPAREN);
				accept(TokenType.SEMI);
				stmtsList.add(factory.makeConstructorInvokation(tmp, expL));
			} else {
				returnMethod();
				noConstructorInvokation = true;
			}
		}
		while (peek(TokenType.SUPER) && (!noConstructorInvokation)) {
			Token tmp1 = accept(TokenType.SUPER);
			accept(TokenType.LPAREN);
			Token tmp2 = accept(TokenType.IDENT);
			accept(TokenType.RPAREN);
			if (peek(TokenType.LPAREN)) {
				accept(TokenType.LPAREN);
				Tree expL = parseExprList();
				accept(TokenType.RPAREN);
				accept(TokenType.SEMI);
				stmtsList.add(factory.makeConstructorInvokation(new Token(tmp1
						.getLine(), tmp1.getCol(), tmp1.getType(), tmp2
						.getText()), expL));
			} else {
				returnMethod();
				returnMethod();
				returnMethod();
				returnMethod();
				noConstructorInvokation = true;
			}
		}
		while (!peek(TokenType.RBRACE)) {
			stmtsList.add(parseBlockStatement());
		}
		Tree body = factory.makeBlock(stmtsList.toArray(new Tree[0]));
		Tree params = factory.makeList(paramList.toArray(new Tree[0]));
		Tree result = factory.makeConstructorDeclaration(modl, tok, throwsList,
				params, body, currentMethodVar++);
		accept(TokenType.RBRACE);
		return result;
	}

	/**
	 * Method that parses a list of expression. The expressions are separated by
	 * ",". The method is useful to parse argument-lists in a method-invocation.
	 * 
	 * @return a tree (ListTree) representing the list of expressions
	 * @throws ParserException
	 *             if an error occur during parsing the expression, or if a
	 *             comma is misplaced
	 */
	protected Tree parseExprList() throws ParserException {
		List<Tree> expL = new ArrayList<Tree>();
		boolean forceOneMoreExpr = false;
		while ((!peek(TokenType.RPAREN)) || forceOneMoreExpr) {
			forceOneMoreExpr = false;
			expL.add(parseExpr());
			if (peek(TokenType.RPAREN)) {
			} else {
				accept(TokenType.COMMA);
				forceOneMoreExpr = true;
			}
		}
		return factory.makeList(expL.toArray(new Tree[0]));
	}

	/**
	 * Method that parses a single declaration, may it be a
	 * parameter-declaration or the declaration of a local variable.
	 * 
	 * @return a tree representing a single declaration
	 * @throws ParserException
	 *             if an error occurs, that means if the syntactic structure is
	 *             wrong
	 */
	protected Tree parsedecl() throws ParserException {
		Type typ = parseType(false);
		Token token = accept(TokenType.IDENT);
		return factory.makeDecl(token, typ, currentLocalVar++);
	}

	/**
	 * Method that parses a parameter-list in a method-declaration for example.
	 * Therefore the method {@link parser.Parser#parsedecl()} is used.
	 * 
	 * @return a list of trees; one tree represents one parameter
	 * @throws ParserException
	 *             if an error occurs in the subroutines, means when the
	 *             syntactical structure is wrong
	 */
	protected List<Tree> parseParamList() throws ParserException {
		List<Tree> paramList = new ArrayList<Tree>();
		boolean mustBeOneMoreDecl = false;
		while ((!peek(TokenType.RPAREN)) || mustBeOneMoreDecl) {
			mustBeOneMoreDecl = false;
			paramList.add(parsedecl());
			if (peek(TokenType.COMMA)) {
				accept(TokenType.COMMA);
				mustBeOneMoreDecl = true;
			} else if (peek(TokenType.RPAREN)) {
			} else {
				accept(TokenType.COMMA, TokenType.RPAREN);
			}
		}
		return paramList;
	}

	/**
	 * Method that parses a throws sequence during constructor or method
	 * declaration. The possible exception are listed, separated by commas
	 * 
	 * @return list of types representing each exception that could by thrown
	 * @throws ParserException
	 *             if the syntactical structure is wrong
	 */
	protected List<Type> parseThrows() throws ParserException {
		List<Type> throwsList = new ArrayList<Type>();
		if (peek(TokenType.THROWS)) {
			accept(TokenType.THROWS);
			throwsList.add(this
					.toPrimitiveAndReferenceType(accept(TokenType.IDENT)));
			while (peek(TokenType.COMMA)) {
				accept(TokenType.COMMA);
				throwsList.add(this
						.toPrimitiveAndReferenceType(accept(TokenType.IDENT)));
			}
		}
		return throwsList;
	}

	/**
	 * Method that parses only the header of a method and transforms this to an
	 * AST. The header or signature of a method contains the parameters and the
	 * name. The header also contains all modifiers, the return type as well as
	 * the throws-list.
	 * 
	 * @param modl
	 *            the list of all modifiers, describing this method nearer
	 * @param name
	 *            token that represents the name of the method
	 * @param typ
	 *            type specifying the type of the returned value
	 * @return a subtree that represents the header of the given method
	 * @throws ParserException
	 *             if an error occurs, that means if the syntactical structure
	 *             has errors
	 */
	protected Tree parseMethodHeader(List<Modifiers> modl, Token name, Type typ)
			throws ParserException {
		List<Tree> paramList = new ArrayList<Tree>();
		List<Type> throwsList = new ArrayList<Type>();
		accept(TokenType.LPAREN);
		paramList = parseParamList();
		accept(TokenType.RPAREN);
		throwsList = parseThrows();
		return factory.makeMethodHeader(modl, name, typ, factory
				.makeList(paramList.toArray(new Tree[0])), throwsList);
	}

	/**
	 * Method that parses a complete SO-method. Beyond the method header, it
	 * consists of the body containing the code to execute when the method is
	 * invoked.
	 * 
	 * @param modl
	 *            list of all modifiers, limiting the accessibility or giving
	 *            certain attitudes
	 * @param name
	 *            token representing the name of the method to declare
	 * @param typ
	 *            type of the value to return at the end of the execution
	 * @param interfaceTyp
	 *            type of the class the method is part of, needed to specify the
	 *            type of the implicit argument this-pointer
	 * @return a node representing the declaration of a method
	 * @throws ParserException
	 *             if any error occurs due to syntacticly faults
	 */
	protected Tree parseMethod(List<Modifiers> modl, Token name, Type typ,
			Type interfaceTyp) throws ParserException {
		List<Tree> paramList = new ArrayList<Tree>();
		List<Type> throwsList = new ArrayList<Type>();
		accept(TokenType.LPAREN);
		paramList = parseParamList();
		accept(TokenType.RPAREN);
		if (!modl.contains(Modifiers.STATIC)) {
			paramList.add(0, factory.makeDecl(new Token(-1, -1,
					TokenType.IDENT, "this"), interfaceTyp, currentLocalVar++));
		}
		Tree parameters = factory.makeList(paramList.toArray(new Tree[0]));
		throwsList = parseThrows();
		Tree body = parseStmt();
		return factory.makeMethodDeclaration(modl, name, typ, parameters,
				throwsList, body, currentMethodVar++);
	}

	/**
	 * Method that parses statements, or more exactly this method decides which
	 * subroutine to call for parsing all possible statements. It is decided by
	 * the first Token.
	 * 
	 * @return a tree, parsed by subroutine, representing a statement given by
	 *         the token stream
	 * @throws ParserException
	 *             if any error occurs due to wrong syntax
	 */
	protected Tree parseStmt() throws ParserException {
		if (peek(TokenType.OUT)) {
			return parseOutputStatement();
		} else if (peek(TokenType.IF)) {
			return parseIfElse();
		} else if (peek(TokenType.WHILE)) {
			return parseWhileLoop();
		} else if (peek(TokenType.FOR)) {
			return parseForStatement();
		} else if (peek(TokenType.LBRACE)) {
			return parseBlock();
		} else if (peek(TokenType.SEMI)) {
			return factory.makeEmptyStatement(accept(TokenType.SEMI));
		} else if (peek(TokenType.SWITCH)) {
			return parseSwitchStatement();
		} else if (peek(TokenType.BREAK)) {
			return factory.makeBreakStatement(accept(TokenType.BREAK));
		} else if (peek(TokenType.THROW)) {
			return parseThrowStatement();
		} else if (peek(TokenType.TRY)) {
			return parseTryStatement();
		} else if (peek(TokenType.RETURN)) {
			return parseReturnStatement();
		} else {
			return parseExpressionStatement();
		}
	}

	/**
	 * One of the subroutines, named in {@link parser.Parser#parseStmt()}. This
	 * subroutine parses an output expression and returns the corresponding
	 * abstract syntax tree.
	 * 
	 * @return a tree representing an output statement
	 * @throws ParserException
	 *             if any syntax error occurs
	 */
	protected Tree parseOutputStatement() throws ParserException {
		Token tok = accept(TokenType.OUT);
		accept(TokenType.LPAREN);
		Tree exp = parseExpr();
		accept(TokenType.RPAREN);
		accept(TokenType.SEMI);
		return factory.makeOutput(tok, exp);
	}

	/**
	 * Method parsing an input-expression, specified by the SO-Grammar.
	 * 
	 * @return a tree that represents the corresponding input-expression
	 * @throws ParserException
	 *             if a syntactical fault is made
	 */
	protected Tree parseInput() throws ParserException {
		Token tok = accept(TokenType.IN);
		accept(TokenType.LPAREN);
		Type typ = parseType(false);
		accept(TokenType.RPAREN);
		accept(TokenType.SEMI);
		return factory.makeInput(tok, typ);
	}

	/**
	 * Subroutine of {@link parser.Parser#parseStmt()}. Method parses an
	 * If-Statement, no matter if only "if" or "if-else". The corresponding tree
	 * is returned as an AST.
	 * 
	 * @return a tree representing the given code-sequence
	 * @throws ParserException
	 *             if any syntax error occurs
	 */
	protected Tree parseIfElse() throws ParserException {
		Token token = accept(TokenType.IF);
		accept(TokenType.LPAREN);
		Tree cond = parseExpr();
		accept(TokenType.RPAREN);
		Tree trueStmt = parseStmt();
		if (peek(TokenType.ELSE)) {
			accept(TokenType.ELSE);
			Tree falseStmt = parseStmt();
			return factory.makeIfElse(token, cond, trueStmt, falseStmt);
		} else {
			return factory.makeIf(token, cond, trueStmt);
		}
	}

	/**
	 * Subroutine of {@link parser.Parser#parseStmt()}. This method transforms a
	 * while-loop, given as a token stream, to an abstract syntax tree.
	 * 
	 * @return a node representing exactly this while-loop
	 * @throws ParserException
	 *             if any syntax fault is made
	 */
	protected Tree parseWhileLoop() throws ParserException {
		Token token = accept(TokenType.WHILE);
		accept(TokenType.LPAREN);
		Tree cond = parseExpr();
		accept(TokenType.RPAREN);
		Tree body = parseStmt();
		return factory.makeWhile(token, cond, body);
	}

	/**
	 * Subroutine of {@link parser.Parser#parseStmt()}. This method parses a
	 * token stream to a for-loop, specified by SO-Grammar.
	 * 
	 * @return the AST representing the given for-loop
	 * @throws ParserException
	 *             if any syntax error occurs
	 */
	protected Tree parseForStatement() throws ParserException {
		Tree forInit = null;
		Tree forUpdate = null;
		Token tok = accept(TokenType.FOR);
		accept(TokenType.LPAREN);
		if (peek(TokenType.SEMI)) {
			forInit = factory.makeList(factory
					.makeEmptyStatement(accept(TokenType.SEMI)));
		} else {
			forInit = parseStatementList(TokenType.SEMI);
			accept(TokenType.SEMI);
		}
		Tree cond = parseExpr();
		Token tmp = accept(TokenType.SEMI);
		if (peek(TokenType.RPAREN)) {
			forUpdate = factory.makeList(factory.makeEmptyStatement(tmp));
		} else {
			forUpdate = parseStatementList(TokenType.RPAREN);
		}
		accept(TokenType.RPAREN);
		Tree body = parseStmt();
		return factory.makeForLoop(tok, forInit, cond, forUpdate, body);
	}

	/**
	 * Parsing method, transforming a given list of expression-statement (see
	 * SO-Grammar) from token stream to a tree.
	 * 
	 * @param t
	 *            token representing the stop token, means the token this method
	 *            is determined
	 * @return a AST representing the given list of expression-statements
	 * @throws ParserException
	 *             if any syntax fault was made
	 */
	protected Tree parseStatementList(TokenType t) throws ParserException {
		List<Tree> tmpList = new ArrayList<Tree>();
		tmpList.add(parseExpressionStatement());
		while (!peek(t)) {
			accept(TokenType.COMMA);
			tmpList.add(parseExpressionStatement());
		}
		return factory.makeList(tmpList.toArray(new Tree[0]));
	}

	/**
	 * Method that parses a block. That means it calls subroutines for
	 * block-statements ({@link parser.Parser#parseBlockStatement()}) and
	 * transforms everything to an AST (BlockTree).
	 * 
	 * @return a tree representing a given block
	 * @throws ParserException
	 *             if any syntax error occurs
	 */
	protected Tree parseBlock() throws ParserException {
		List<Tree> treeList = new ArrayList<Tree>();
		accept(TokenType.LBRACE);
		while (!peek(TokenType.RBRACE)) {
			treeList.add(parseBlockStatement());
		}
		accept(TokenType.RBRACE);
		return factory.makeBlock(treeList.toArray(new Tree[0]));
	}

	/**
	 * Method that parses a block-statement. That can be: a local variable
	 * declaration, or assignment, or only a statement (
	 * {@link parser.Parser#parseStmt()})
	 * 
	 * @return a tree representing one given block-statement
	 * @throws ParserException
	 *             if any syntactical fault was made
	 */
	protected Tree parseBlockStatement() throws ParserException {
		// Local variable declaration
		if (peek(TokenType.BOOL_TYPE, TokenType.INT_TYPE, TokenType.LONG_TYPE,
				TokenType.FLOAT_TYPE, TokenType.DOUBLE_TYPE,
				TokenType.CHAR_TYPE, TokenType.STRING_TYPE)) {
			Type ty = parseType(false);
			Token id = accept(TokenType.IDENT);
			if (peek(TokenType.ASSIGN)) {
				Token tmp = accept(TokenType.ASSIGN);
				Tree exp = parseExpr();
				accept(TokenType.SEMI);
				return factory.makeAssign(tmp, factory.makeDecl(id, ty,
						currentLocalVar++), exp);
			} else {
				accept(TokenType.SEMI);
				return factory.makeDecl(id, ty, currentLocalVar++);
			}
		}
		// local variable assignment
		if (peek(TokenType.IDENT)) {
			accept(TokenType.IDENT);
			if (peek(TokenType.IDENT)) {
				this.returnMethod();
				Type ty = parseType(false);
				Token id = accept(TokenType.IDENT);
				if (peek(TokenType.ASSIGN)) {
					Token tmp = accept(TokenType.ASSIGN);
					Tree exp = parseExpr();
					accept(TokenType.SEMI);
					return factory.makeAssign(tmp, factory.makeDecl(id, ty,
							currentLocalVar++), exp);
				} else {
					accept(TokenType.SEMI);
					return factory.makeDecl(id, ty, currentLocalVar++);
				}
			} else {
				this.returnMethod();
			}
		}
		// normal statement
		return parseStmt();
	}

	/**
	 * Method that parses a switch statement, specified by SO-Grammar and given
	 * by the token stream. It is transform to an abstract syntax tree.
	 * 
	 * @return a node representing the given switch-statement
	 * @throws ParserException
	 *             is thrown if any syntactical error occurs
	 */
	protected Tree parseSwitchStatement() throws ParserException {
		Token tok = accept(TokenType.SWITCH);
		accept(TokenType.LPAREN);
		Tree expr = parseExpr();
		accept(TokenType.RPAREN);
		Tree body = parseSwitchBlock();
		return factory.makeSwitch(tok, expr, body);
	}

	/**
	 * Method that parses the body of a switch-statement. Thus it is a
	 * subroutine of {@link parser.Parser#parseSwitchStatement()}. The method
	 * lasts until no switch-group is there any more. A group has the following
	 * syntax: case expr : statements;. The last group can be a default block
	 * (default: ...) and must be the end of the switch-body. A BlockTree is
	 * returned.
	 * 
	 * @return a BlockTree representing the body of the given switch statement
	 * @throws ParserException
	 *             if any syntactical error occurs
	 */
	protected Tree parseSwitchBlock() throws ParserException {
		accept(TokenType.LBRACE);
		List<Tree> switchBlockStatements = new ArrayList<Tree>();
		while (!peek(TokenType.RBRACE)) {
			// default-group
			if (peek(TokenType.DEFAULT)) {
				List<Tree> blockStatements = new ArrayList<Tree>();
				Token tmp = accept(TokenType.DEFAULT);
				accept(TokenType.COLON);
				while (!peek(TokenType.RBRACE)) {
					blockStatements.add(parseBlockStatement());
				}
				Tree statements = factory.makeList(blockStatements
						.toArray(new Tree[0]));
				switchBlockStatements.add(factory.makeSwitchGroup(tmp, null,
						statements));
			}
			// case-group
			else if (peek(TokenType.CASE)) {
				List<Tree> blockStatements = new ArrayList<Tree>();
				Token tmp = accept(TokenType.CASE);
				Tree expr = parseExpr();
				accept(TokenType.COLON);
				while (!peek(TokenType.RBRACE, TokenType.DEFAULT,
						TokenType.CASE)) {
					blockStatements.add(parseBlockStatement());
				}
				Tree statements = factory.makeList(blockStatements
						.toArray(new Tree[0]));
				switchBlockStatements.add(factory.makeSwitchGroup(tmp, expr,
						statements));
			}
			// syntax error will now follow
			else {
				accept(TokenType.DEFAULT, TokenType.CASE, TokenType.RBRACE);
			}
		}
		accept(TokenType.RBRACE);
		return factory.makeBlock(switchBlockStatements.toArray(new Tree[0]));
	}

	/**
	 * Method that parses a throw statement. A throw statement gets an object,
	 * the exception with special constructor and method. An exception must
	 * inherit from superclass Exception. The message of the exception is
	 * printed on the screen and the program (SO) will be aborted and return
	 * error value -1.
	 * 
	 * @return a tree, representing the given throw statement
	 * @throws ParserException
	 *             if any syntax fault was made
	 */
	protected Tree parseThrowStatement() throws ParserException {
		Token tok = accept(TokenType.THROW);
		Tree expr = parseExpr();
		accept(TokenType.SEMI);
		return factory.makeThrowException(tok, expr);
	}

	/**
	 * Method that parses a try-statement. The try block contains the code to be
	 * executed. If the SO-Code-sequence will throw an exception, the
	 * catch-block is invoked when the thrown exception has a specified type.
	 * Then the code in catch-block will be executed. The try-block is
	 * abandoned. At the end of both blocks, there can be an optionally
	 * finally-block. This code is executed in all cases.
	 * 
	 * @return a tree representing such a try-statement, consisting of try-,
	 *         catch- and finally-block
	 * @throws ParserException
	 *             if any syntactical fault occurs
	 */
	protected Tree parseTryStatement() throws ParserException {
		Token tok = accept(TokenType.TRY);
		Tree blockToTry = this.parseBlock();
		Token tok1 = accept(TokenType.CATCH);
		accept(TokenType.LPAREN);
		Type ty = parseType(false);
		Token tok2 = accept(TokenType.IDENT);
		Tree param = factory.makeDecl(tok2, ty, currentLocalVar++);
		accept(TokenType.RPAREN);
		Tree catchBlock = parseBlock();
		Tree catchTree = factory.makeCatch(tok1, param, catchBlock);
		Tree finallyBlock = null;
		if (peek(TokenType.FINALLY)) {
			accept(TokenType.FINALLY);
			finallyBlock = parseBlock();
		} else {
			finallyBlock = factory.makeBlock();
		}
		return factory.makeTry(tok, blockToTry, catchTree, finallyBlock);
	}

	/**
	 * Method that parses a return statement. A return statement consist of the
	 * token with TokenType.RETURN and can be followed by an expression, that
	 * will be returned at that point in SO-Code. In the other case it must be
	 * the end of a void-method.
	 * 
	 * @return tree representing the given return-statement
	 * @throws ParserException
	 *             if any syntax error occurs
	 */
	protected Tree parseReturnStatement() throws ParserException {
		Token tok = accept(TokenType.RETURN);
		Tree expr = null;
		if (!peek(TokenType.SEMI)) {
			expr = parseExpr();
		}
		accept(TokenType.SEMI);
		return factory.makeReturn(tok, expr);
	}

	/**
	 * One of the core problems during compiler-construction process. This
	 * method parses an expression statement. The needed subroutines are called.
	 * (compare SO-Grammar in documentation), e.g. a pre-increment-expression,
	 * post-increment-expression, method-invocation, assignment and a lot more.
	 * Therefore the code contains more comments at each state of parsing. The
	 * expression-statement is transformed to the corresponding AST.
	 * 
	 * @return an abstract syntax tree representing the given
	 *         expression-statement
	 * @throws ParserException
	 */
	protected Tree parseExpressionStatement() throws ParserException {
		// StatementExpression starting with increment- decrement operator
		if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
			Token to = accept(TokenType.INCREMENT, TokenType.DECREMENT);
			Tree expr = unaryExpr();
			accept(TokenType.SEMI);
			return factory.makePreIncDec(to, expr);
		}
		// StatementExpression starting with this
		if (peek(TokenType.THIS)) {
			Token tok = accept(TokenType.THIS);
			if (!peek(TokenType.POINT)) {
				throw ParserException.UnexpectedToken(
						accept(TokenType.values()), TokenType.POINT);
			} else {
				Tree baum = this.parseExtendedFieldArrayMethodInv(factory
						.makeThisAccess(tok), true, true);
				if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
					Token t = accept(TokenType.INCREMENT, TokenType.DECREMENT);
					accept(TokenType.SEMI);
					return factory.makePostIncDec(t, baum);
				}
				if (this.isNextTokenAAssignmentOp()) {
					Token t = accept(TokenType.ASSIGN, TokenType.DIVIDEASSIGN,
							TokenType.MULASSIGN, TokenType.MODULOASSIGN,
							TokenType.PLUSASSIGN, TokenType.MINUSASSIGN,
							TokenType.SHIFTLEFTASSIGN,
							TokenType.SHIFTRIGHTASSIGN, TokenType.BITANDASSIGN,
							TokenType.BITORASSIGN, TokenType.BITXORASSIGN);
					Tree tr = parseExpr();
					accept(TokenType.SEMI);
					return factory.makeAssign(t, baum, tr);
				} else {
					accept(TokenType.SEMI);
					return baum;
				}
			}
		}
		// StatementExpression starting with super
		if (peek(TokenType.SUPER)) {
			Token tok = accept(TokenType.SUPER);
			accept(TokenType.LPAREN);
			Type ty = this.toPrimitiveAndReferenceType(accept(TokenType.IDENT));
			accept(TokenType.RPAREN);
			Tree zwischenStand = factory.makeSuperAccess(tok, ty);
			if (!peek(TokenType.POINT)) {
				throw ParserException.UnexpectedToken(
						accept(TokenType.values()), TokenType.POINT);
			}
			Tree baum = this.parseExtendedFieldArrayMethodInv(zwischenStand,
					true, true);
			if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
				Token t = accept(TokenType.INCREMENT, TokenType.DECREMENT);
				accept(TokenType.SEMI);
				return factory.makePostIncDec(t, baum);
			}
			if (this.isNextTokenAAssignmentOp()) {
				Token t = accept(TokenType.ASSIGN, TokenType.DIVIDEASSIGN,
						TokenType.MULASSIGN, TokenType.MODULOASSIGN,
						TokenType.PLUSASSIGN, TokenType.MINUSASSIGN,
						TokenType.SHIFTLEFTASSIGN, TokenType.SHIFTRIGHTASSIGN,
						TokenType.BITANDASSIGN, TokenType.BITORASSIGN,
						TokenType.BITXORASSIGN);
				Tree tr = parseExpr();
				accept(TokenType.SEMI);
				return factory.makeAssign(t, baum, tr);
			} else {
				accept(TokenType.SEMI);
				return baum;
			}
		}
		// StatementExpression starting with an identifier
		if (peek(TokenType.IDENT)) {
			Token tok = accept(TokenType.IDENT);
			if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
				Token t = accept(TokenType.INCREMENT, TokenType.DECREMENT);
				accept(TokenType.SEMI);
				return factory.makePostIncDec(t, factory
						.makeLocalVarAccess(tok));
			}
			// static Method Invocation within own class
			if (peek(TokenType.LPAREN)) {
				List<Tree> argList = new ArrayList<Tree>();
				accept(TokenType.LPAREN);
				while (!peek(TokenType.RPAREN)) {
					argList.add(this.parseExpr());
					if (!peek(TokenType.RPAREN)) {
						accept(TokenType.COMMA);
					}
				}
				accept(TokenType.RPAREN);
				accept(TokenType.SEMI);
				return factory.makeMethodInvocationStaticWithinOwnClass(tok,
						argList.toArray(new Tree[argList.size()]));
			}
			// LocalArrayAccess
			if (peek(TokenType.LSQBRAC)) {
				boolean decl = false;
				int countArrayDepth = 0;
				List<Tree> indList = new ArrayList<Tree>();
				while (peek(TokenType.LSQBRAC)) {
					accept(TokenType.LSQBRAC);
					if (peek(TokenType.RSQBRAC) || decl) {
						accept(TokenType.RSQBRAC);
						countArrayDepth++;
						decl = true;
					} else {
						indList.add(this.parseExpr());
						accept(TokenType.RSQBRAC);
					}
				}
				if (decl) {
					assert (indList.size() == 0) : "Never mix up [] and [expr]";
					Type ty = this.toPrimitiveAndReferenceType(tok);
					while (countArrayDepth > 0) {
						ty = this.toArrayType(ty);
						countArrayDepth--;
					}
					Token ident = accept(TokenType.IDENT);
					Tree left = factory.makeDecl(ident, ty, currentLocalVar++);
					if (this.isNextTokenAAssignmentOp()) {
						Tree baum = this.parseAssignment(left);
						accept(TokenType.SEMI);
						return baum;
					} else {
						accept(TokenType.SEMI);
						return left;
					}
				}
				Tree left = factory.makeLocalArrayAccess(tok, indList);
				if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
					Token t = accept(TokenType.INCREMENT, TokenType.DECREMENT);
					accept(TokenType.SEMI);
					return factory.makePostIncDec(t, left);
				}
				if (this.isNextTokenAAssignmentOp()) {
					Tree baumle = this.parseAssignment(left);
					accept(TokenType.SEMI);
					return baumle;
				}
				if (peek(TokenType.POINT)) {
					Tree baum = this.parseExtendedFieldArrayMethodInv(left,
							true, true);
					if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
						Token t = accept(TokenType.INCREMENT,
								TokenType.DECREMENT);
						accept(TokenType.SEMI);
						return factory.makePostIncDec(t, baum);
					}
					if (this.isNextTokenAAssignmentOp()) {
						Tree baumle = this.parseAssignment(baum);
						accept(TokenType.SEMI);
						return baumle;
					}
					return baum;
				} else {
					throw ParserException.UnexpectedToken(accept(TokenType
							.values()), TokenType.POINT);
				}
			}
			//
			if (!peek(TokenType.POINT)) {
				throw ParserException.UnexpectedToken(
						accept(TokenType.values()), TokenType.POINT);
			}
			// Complex Method Invocation, Fieldaccess or ArrayAccess
			Tree baum = this.parseExtendedFieldArrayMethodInv(factory
					.makeFieldAccess(tok, null), true, true);
			if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
				Token t = accept(TokenType.INCREMENT, TokenType.DECREMENT);
				accept(TokenType.SEMI);
				return factory.makePostIncDec(t, baum);
			}
			if (this.isNextTokenAAssignmentOp()) {
				Tree baumle = this.parseAssignment(baum);
				accept(TokenType.SEMI);
				return baumle;
			}
			return baum;
		}
		throw ParserException.UnexpectedToken(accept(TokenType.values()),
				TokenType.DECREMENT, TokenType.THIS, TokenType.SUPER,
				TokenType.IDENT, TokenType.INCREMENT);
	}

	/**
	 * Method that analyse the next token. If the next token is a kind of
	 * assignment, e.g. *=,+=,-=, etc. this method returns true. Its a kind of
	 * syntactic sugar because this is a often used request.
	 * 
	 * @return true if the current token is a kind of assignment
	 */
	protected boolean isNextTokenAAssignmentOp() {
		return peek(TokenType.ASSIGN, TokenType.DIVIDEASSIGN,
				TokenType.MULASSIGN, TokenType.MODULOASSIGN,
				TokenType.PLUSASSIGN, TokenType.MINUSASSIGN,
				TokenType.SHIFTLEFTASSIGN, TokenType.SHIFTRIGHTASSIGN,
				TokenType.BITANDASSIGN, TokenType.BITORASSIGN,
				TokenType.BITXORASSIGN);
	}

	/**
	 * Method that parses an expression. The method calls a subroutine, compare
	 * {@link parser.Parser#condExpr()}. A corresponding tree is returned. The
	 * order the called methods specifies the priority of each operation. (minor
	 * prior operation first)
	 * 
	 * @return an abstract syntax tree representing the given expression in
	 *         SO-Code
	 * @throws ParserException
	 *             if any syntax error occurs
	 */
	public Tree parseExpr() throws ParserException {
		return condExpr();
	}

	/**
	 * Subroutine of {@link parser.Parser#parseExpr()}. Method parses a
	 * conditional expression of kind expr ? expr : expr. The needed subroutines
	 * are called. If there isn't a conditional expression, the token stream is
	 * given unchanged to the next method at a lower stage. That will be the
	 * scheme for all expression-parsing methods.
	 * 
	 * @return a tree corresponding at the code given by the token stream
	 * @throws ParserException
	 *             if any syntax error occurs
	 */
	protected Tree condExpr() throws ParserException {
		Tree cond = orExpr();
		if (peek(TokenType.QMARK)) {
			Token token = accept(TokenType.QMARK);
			Tree trueExpr = condExpr();
			accept(TokenType.COLON);
			Tree falseExpr = condExpr();
			return factory.makeCond(token, cond, trueExpr, falseExpr);
		}
		return cond;
	}

	/**
	 * Another expression-parsing method. This method parses an or-expression.
	 * if there is no or-expression, the token stream will be given unchanged to
	 * {@link parser.Parser#andExpr()}. Or-Expression: expr || expr
	 * 
	 * @return a tree representing the or-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree orExpr() throws ParserException {
		Tree left = andExpr();
		while (peek(TokenType.OR)) {
			Token token = accept(TokenType.OR);
			Tree right = andExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses an and-expression.
	 * if there is no and-expression, the token stream will be given unchanged
	 * to {@link parser.Parser#bitOrExpr()}. And-Expression: expr && expr
	 * 
	 * @return a tree representing the and-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree andExpr() throws ParserException {
		Tree left = bitOrExpr();
		while (peek(TokenType.AND)) {
			Token token = accept(TokenType.AND);
			Tree right = bitOrExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses a
	 * bit-or-expression. if there is no bit-or-expression, the token stream
	 * will be given unchanged to {@link parser.Parser#bitXorExpr()}.
	 * Bit-Or-Expression: expr | expr
	 * 
	 * @return a tree representing the bit-or-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree bitOrExpr() throws ParserException {
		Tree left = bitXorExpr();
		while (peek(TokenType.BITOR)) {
			Token token = accept(TokenType.BITOR);
			Tree right = bitXorExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses a
	 * bit-xor-expression. if there is no bit-xor-expression, the token stream
	 * will be given unchanged to {@link parser.Parser#bitAndExpr()}.
	 * bit-xor-Expression: expr ^^ expr
	 * 
	 * @return a tree representing the bit-xor-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree bitXorExpr() throws ParserException {
		Tree left = bitAndExpr();
		while (peek(TokenType.XOR)) {
			Token token = accept(TokenType.XOR);
			Tree right = bitAndExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses a
	 * bit-and-expression. if there is no bit-and-expression, the token stream
	 * will be given unchanged to {@link parser.Parser#eqNeqExpr()}.
	 * bit-and-Expression: expr & expr
	 * 
	 * @return a tree representing the bit-and-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree bitAndExpr() throws ParserException {
		Tree left = eqNeqExpr();
		while (peek(TokenType.BITAND)) {
			Token token = accept(TokenType.BITAND);
			Tree right = eqNeqExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses an
	 * equal-notequal-expression. if there is no equal-notequal-expression, the
	 * token stream will be given unchanged to {@link parser.Parser#relExpr()}.
	 * equal-notequal-Expression: expr == / != expr
	 * 
	 * @return a tree representing the equal-notequal-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree eqNeqExpr() throws ParserException {
		Tree left = relExpr();
		while (peek(TokenType.EQ, TokenType.NE)) {
			Token token = accept(TokenType.EQ, TokenType.NE);
			Tree right = relExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses a
	 * relational-expression. if there is no relational-expression, the token
	 * stream will be given unchanged to {@link parser.Parser#shiftLRExpr()}.
	 * relational-Expression: expr < / <= / > / >= expr
	 * 
	 * @return a tree representing the relational-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree relExpr() throws ParserException {
		Tree left = shiftLRExpr();
		while (peek(TokenType.GT, TokenType.GE, TokenType.LE, TokenType.LT)) {
			Token token = accept(TokenType.GT, TokenType.GE, TokenType.LE,
					TokenType.LT);
			Tree right = shiftLRExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses
	 * shift-left-right-expression. if there is no shift-expression, the token
	 * stream will be given unchanged to {@link parser.Parser#addSubExpr()}.
	 * shift-Expression: expr << / >> expr
	 * 
	 * @return a tree representing the shift-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree shiftLRExpr() throws ParserException {
		Tree left = addSubExpr();
		while (peek(TokenType.SHL, TokenType.SHR)) {
			Token token = accept(TokenType.SHL, TokenType.SHR);
			Tree right = addSubExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses an
	 * additive-expression. if there is no additive-expression, the token stream
	 * will be given unchanged to {@link parser.Parser#mulDivModExpr()}.
	 * additive-Expression: expr + / - expr
	 * 
	 * @return a tree representing the additive-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree addSubExpr() throws ParserException {
		Tree left = mulDivModExpr();
		while (peek(TokenType.PLUS, TokenType.MINUS)) {
			Token token = accept(TokenType.PLUS, TokenType.MINUS);
			Tree right = mulDivModExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses a
	 * multiplicative-expression. if there is no multiplicative-expression, the
	 * token stream will be given unchanged to {@link parser.Parser#powExpr()}.
	 * multiplicative-Expression: expr * [or] / [or] % expr
	 * 
	 * @return a tree representing the multiplicative-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree mulDivModExpr() throws ParserException {
		Tree left = powExpr();
		while (peek(TokenType.DIVORSLASH, TokenType.MOD, TokenType.MUL)) {
			Token token = accept(TokenType.DIVORSLASH, TokenType.MOD,
					TokenType.MUL);
			Tree right = powExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses a power-expression.
	 * if there is no power-expression, the token stream will be given unchanged
	 * to {@link parser.Parser#unaryExpr()}. power-Expression: expr ^ expr
	 * 
	 * @return a tree representing the power-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree powExpr() throws ParserException {
		Tree left = unaryExpr();
		while (peek(TokenType.HOCH)) {
			Token token = accept(TokenType.HOCH);
			Tree right = unaryExpr();
			left = factory.makeBinOp(token, left, right);
		}
		return left;
	}

	/**
	 * Another expression-parsing method. This method parses an
	 * unary-expression. if there is no unary-expression, the token stream will
	 * be given unchanged to {@link parser.Parser#primary()}. unary-Expression:
	 * + [or] - [0r] ! expr
	 * 
	 * @return a tree representing the given unary-expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree unaryExpr() throws ParserException {
		if (peek(TokenType.PLUS, TokenType.MINUS, TokenType.NOT)) {
			Token token = accept(TokenType.PLUS, TokenType.MINUS, TokenType.NOT);
			Tree expr = unaryExpr();
			return factory.makeUnOp(token, expr);
		}
		return primary();
	}

	/**
	 * Last expression-parsing method at lowest stage. This method parses all
	 * expressions that are part of primary (compare SO-Grammar), e.g.:
	 * Literals, variable-usage, method-invocations, array-access. Thus it is
	 * another core-method for the parser. For more details watch the
	 * source-code and the additionally comments in the source-code.
	 * 
	 * @return a tree representing a primary expression
	 * @throws ParserException
	 *             if a syntactical error occurs
	 */
	protected Tree primary() throws ParserException {
		// Literal
		TokenType[] literalArray = new TokenType[] { TokenType.INT_LITERAL,
				TokenType.DOUBLE_LITERAL, TokenType.FLOAT_LITERAL,
				TokenType.LONG_LITERAL, TokenType.STRING_LITERAL,
				TokenType.CHAR_LITERAL, TokenType.NULL_LITERAL,
				TokenType.TRUE_LITERAL, TokenType.FALSE_LITERAL };
		if (peek(literalArray)) {
			Token to = accept(literalArray);
			return factory.makeLiteral(to);
		}
		// CastExpression
		if (peek(TokenType.CAST)) {
			Token tok = accept(TokenType.CAST);
			accept(TokenType.LPAREN);
			Type ty = parseType(false);
			accept(TokenType.RPAREN);
			Tree tr = unaryExpr();
			return factory.makeExplicitTypeCast(tok, ty, tr);
		}
		// InputExpression
		if (peek(TokenType.IN)) {
			Token tok = accept(TokenType.IN);
			accept(TokenType.LPAREN);
			Type ty = parseType(false);
			accept(TokenType.RPAREN);
			return factory.makeInput(tok, ty);
		}
		// PreIncDecExpression
		if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
			Token tok = accept(TokenType.INCREMENT, TokenType.DECREMENT);
			Tree exp = unaryExpr();
			return factory.makePreIncDec(tok, exp);
		}
		// ArrayCreation ClassInstanceCreation
		if (peek(TokenType.NEW)) {
			Token tok = accept(TokenType.NEW);
			if (peek(TokenType.IDENT)) {
				Token t = accept(TokenType.IDENT);
				if (peek(TokenType.LPAREN)) {
					// ClassInstanceCreation
					accept(TokenType.LPAREN);
					Type ty = this.toPrimitiveAndReferenceType(t);
					List<Tree> argList = new ArrayList<Tree>();
					while (!peek(TokenType.RPAREN)) {
						argList.add(this.parseExpr());
						if (!peek(TokenType.RPAREN)) {
							accept(TokenType.COMMA);
						}
					}
					accept(TokenType.RPAREN);
					return factory.makeClassInstanceCreation(tok, ty, argList);
				} else {
					returnMethod();
				}
			}
			Type ty = this.toPrimitiveAndReferenceType(accept(TokenType.IDENT,
					TokenType.INT_TYPE, TokenType.LONG_TYPE,
					TokenType.FLOAT_TYPE, TokenType.DOUBLE_TYPE,
					TokenType.CHAR_TYPE, TokenType.STRING_TYPE,
					TokenType.BOOL_TYPE));
			// ArrayCreation
			List<Tree> bouncesList = new ArrayList<Tree>();
			while (peek(TokenType.LSQBRAC)) {
				accept(TokenType.LSQBRAC);
				bouncesList.add(this.parseExpr());
				accept(TokenType.RSQBRAC);
				ty = this.toArrayType(ty);
			}
			return factory.makeNewArray(tok, ty, bouncesList);
		}
		// Expression starting with this
		if (peek(TokenType.THIS)) {
			Token tok = accept(TokenType.THIS);
			if (peek(TokenType.HASDYNAMICTYPE)) {
				Token t = accept(TokenType.HASDYNAMICTYPE);
				Type ty = this.parseType(false);
				return factory.makeDynamicTypeTest(t, factory
						.makeThisAccess(tok), ty);
			}
			if (!peek(TokenType.POINT)) {
				return factory.makeThisAccess(tok);
			} else {
				return this.parseExtendedFieldArrayMethodInv(factory
						.makeThisAccess(tok), true, true);
			}
		}
		// Expression starting with super
		if (peek(TokenType.SUPER)) {
			Token tok = accept(TokenType.SUPER);
			accept(TokenType.LPAREN);
			Type ty = this.toPrimitiveAndReferenceType(accept(TokenType.IDENT));
			accept(TokenType.RPAREN);
			Tree zwischenStand = factory.makeSuperAccess(tok, ty);
			if (peek(TokenType.HASDYNAMICTYPE)) {
				Token t = accept(TokenType.HASDYNAMICTYPE);
				Type type = this.parseType(false);
				return factory.makeDynamicTypeTest(t, zwischenStand, type);
			}
			if (!peek(TokenType.POINT)) {
				return zwischenStand;
			}
			return this.parseExtendedFieldArrayMethodInv(zwischenStand, true,
					true);
		}
		// Expression between LPAREN and RPAREN
		if (peek(TokenType.LPAREN)) {
			accept(TokenType.LPAREN);
			Tree expression = this.parseExpr();
			accept(TokenType.RPAREN);
			if (peek(TokenType.HASDYNAMICTYPE)) {
				Token t = accept(TokenType.HASDYNAMICTYPE);
				Type type = this.parseType(false);
				return factory.makeDynamicTypeTest(t, expression, type);
			}
			if (peek(TokenType.POINT)) {
				return this.parseExtendedFieldArrayMethodInv(expression, true,
						true);
			}
		}
		if (peek(TokenType.IDENT)) {
			Token tok = accept(TokenType.IDENT);
			if (peek(TokenType.HASDYNAMICTYPE)) {
				Token t = accept(TokenType.HASDYNAMICTYPE);
				Type ty = this.parseType(false);
				return factory.makeDynamicTypeTest(t, factory
						.makeLocalVarAccess(tok), ty);
			}
			if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
				Token t = accept(TokenType.INCREMENT, TokenType.DECREMENT);
				return factory.makePostIncDec(t, factory
						.makeLocalVarAccess(tok));
			}
			// Length-Expression
			if (peek(TokenType.POINT)) {
				accept(TokenType.POINT);
				if (peek(TokenType.LENGTH)) {
					Token t = accept(TokenType.LENGTH);
					return factory.makeLengthExpr(t, tok, null);
				}
				returnMethod();
			}
			// static Method Invocation within own class
			if (peek(TokenType.LPAREN)) {
				List<Tree> argList = new ArrayList<Tree>();
				accept(TokenType.LPAREN);
				while (!peek(TokenType.RPAREN)) {
					argList.add(this.parseExpr());
					if (!peek(TokenType.RPAREN)) {
						accept(TokenType.COMMA);
					}
				}
				accept(TokenType.RPAREN);
				return factory.makeMethodInvocationStaticWithinOwnClass(tok,
						argList.toArray(new Tree[argList.size()]));
			}
			// LocalArrayAccess
			if (peek(TokenType.LSQBRAC)) {
				List<Tree> indList = new ArrayList<Tree>();
				while (peek(TokenType.LSQBRAC)) {
					accept(TokenType.LSQBRAC);
					indList.add(this.parseExpr());
					accept(TokenType.RSQBRAC);
				}
				Tree tr = factory.makeLocalArrayAccess(tok, indList);
				if (peek(TokenType.POINT)) {
					tr = this.parseExtendedFieldArrayMethodInv(tr, true, true);
				}
				if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
					Token t = accept(TokenType.INCREMENT, TokenType.DECREMENT);
					return factory.makePostIncDec(t, tr);
				}
				if (peek(TokenType.HASDYNAMICTYPE)) {
					Token t = accept(TokenType.HASDYNAMICTYPE);
					Type ty = this.parseType(false);
					return factory.makeDynamicTypeTest(t, tr, ty);
				}
				return tr;
			}
			// Local Var Usage
			if (!peek(TokenType.POINT)) {
				return factory.makeLocalVarAccess(tok);
			}
			// Complex Method Invocation, Fieldaccess or ArrayAccess
			Tree baum = this.parseExtendedFieldArrayMethodInv(factory
					.makeFieldAccess(tok, null), true, true);
			if (peek(TokenType.INCREMENT, TokenType.DECREMENT)) {
				Token t = accept(TokenType.INCREMENT, TokenType.DECREMENT);
				return factory.makePostIncDec(t, baum);
			}
			if (peek(TokenType.HASDYNAMICTYPE)) {
				Token t = accept(TokenType.HASDYNAMICTYPE);
				Type ty = this.parseType(false);
				return factory.makeDynamicTypeTest(t, baum, ty);
			}
			return baum;
		}
		throw ParserException.UnexpectedToken(accept(TokenType.values()),
				TokenType.LPAREN, TokenType.IDENT, TokenType.SUPER,
				TokenType.THIS, TokenType.NEW, TokenType.INCREMENT,
				TokenType.DECREMENT, TokenType.INT_LITERAL,
				TokenType.DOUBLE_LITERAL, TokenType.CAST);
	}

	/**
	 * Specialised method and very important for parsing object graphs
	 * (a.b.c.d...). One part of an object graph can be a method-invocation, a
	 * field-access or an array-access. The object graph is completely analysed
	 * by calling this method recursively. Therefore it has a few parameters.
	 * 
	 * @param akkumulator
	 *            Tree that represents the object graph until now. It is a kind
	 *            of accumulator and is the tree that is finally returned when
	 *            the object graph is complete.
	 * @param parseMethodInv
	 *            boolean value, can limit the options the object graph can go;
	 *            true -> the current node of the object graph can be a
	 *            Method-invocation
	 * @param parseLengthExp
	 *            boolean value, can limit the options the object graph can go;
	 *            true -> the current node of the object graph can be a
	 *            length-expression and thus the end of this object graph
	 * @return an abstract syntax tree representing either a length-expression
	 *         or a complex object graph
	 * @throws ParserException
	 *             if any syntactical error is detected
	 */
	protected Tree parseExtendedFieldArrayMethodInv(Tree akkumulator,
			boolean parseMethodInv, boolean parseLengthExp)
			throws ParserException {
		if (!peek(TokenType.POINT)) {
			return akkumulator;
		}
		// Near Length-Expression or Near MethodInvocation
		accept(TokenType.POINT);
		if (parseLengthExp || parseMethodInv) {
			Token tok = accept(TokenType.IDENT);
			if (peek(TokenType.POINT)) {
				accept(TokenType.POINT);
				if (parseLengthExp && peek(TokenType.LENGTH)) {
					Token t = accept(TokenType.LENGTH);
					return factory.makeLengthExpr(t, tok, akkumulator);
				}
				if (parseMethodInv && peek(TokenType.LPAREN)) {
					List<Tree> argList = new ArrayList<Tree>();
					accept(TokenType.LPAREN);
					while (!peek(TokenType.RPAREN)) {
						argList.add(this.parseExpr());
						if (!peek(TokenType.RPAREN)) {
							accept(TokenType.COMMA);
						}
					}
					accept(TokenType.RPAREN);
					return factory.makeMethodInvocation(tok, akkumulator,
							argList.toArray(new Tree[argList.size()]));
				}
				returnMethod();
			}
			returnMethod();
		}
		// Near FieldAccess or ArrayAccess
		Token tok = accept(TokenType.IDENT);
		if (peek(TokenType.POINT)) {
			return this.parseExtendedFieldArrayMethodInv(factory
					.makeFieldAccess(tok, akkumulator), parseMethodInv,
					parseLengthExp);
		}
		if (peek(TokenType.LSQBRAC)) {
			List<Tree> indList = new ArrayList<Tree>();
			while (peek(TokenType.LSQBRAC)) {
				accept(TokenType.LSQBRAC);
				indList.add(this.parseExpr());
				accept(TokenType.RSQBRAC);
			}
			if (peek(TokenType.POINT)) {
				return this.parseExtendedFieldArrayMethodInv(factory
						.makeArrayAccess(tok, akkumulator, indList),
						parseMethodInv, parseLengthExp);
			} else {
				return factory.makeArrayAccess(tok, akkumulator, indList);
			}
		} else {
			return factory.makeFieldAccess(tok, akkumulator);
		}
	}

}
// end parser